package json

import (
	"strconv"
	"encoding/json"
	. "mana/buyer"
	"reflect"
	"os"
	"strings"
)

type Jsoner struct {
	JsonInter
	Tester
	JsonArray map[string]string
	abspath   string
}

func JsonWriter(st StreamInter, j Jsoner, dat string) (int, error) {
	Where()
	path := j.abspath + "\\result\\"
	err := os.MkdirAll(path, 0777)
	Check(err)
	filename := j.Name + "." + strings.ToLower(j.Result) + ".json"

	return st.Writer(path+filename, dat)
}

func JsonReader(st StreamInter, path string) (jar map[int]*Jsoner) {
	var indat string
	jar = make(map[int]*Jsoner)
	if strings.Compare(path, "") == 0 {
		indat = os.Args[0]
	} else {
		indat = path
	}

	abspath, list := st.Reader(indat)

	i := 0
	for _, v := range list {
		json := new(Jsoner)
		if json.Filter(v) {

			readjson := st.ReadData(abspath + "\\" + v)
			if json.AssignTester(json.JsonDecoder(readjson), nil) {
				json.abspath = abspath
				jar[i] = json
				i++
			}
		}
	}
	return
}

func (s *Jsoner) Filter(name string) bool {
	narr := strings.Split(name, ".")
	last := narr[len(narr)-1]

	cpv := strings.Compare(last, "json")

	if cpv == 0 {
		s.File = strings.Split(name, ".json")[0]
		return true
	}
	return false
}

func (s *Jsoner) JsonEncoder(t Tester) (string, error) {
	Where()

	by, err := json.Marshal(t)
	return string(by), err

}

func (s *Jsoner) JsonDecoder(result string) interface{} {
	Where()
	var input interface{}

	if s.Request == nil {
		s.Request = make(map[string]string)
	}
	if s.Response == nil {
		s.Response = make(map[string]string)
	}
	if s.Receive == nil {
		s.Receive = make(map[string]string)
	}

	err := json.Unmarshal([]byte(result), &input)
	if err == nil {
		return input
	}
	return nil
}

func (s *Jsoner) AssignTester(input interface{}, name interface{}) bool {
	Where()
	if input == nil {
		return false
	}

	t := &s.Tester
	elem := reflect.ValueOf(t).Elem()
	switch (input).(type) {

	case string:
		{
			println("string")
			foo := (input).(string)
			field := elem.FieldByName(name.(string))
			println(name.(string))
			if field.CanSet() {
				field.SetString(foo)
			} else {
				println("String CanSet Err")
			}
		}

	case []interface{}:
		{
			println("[]interface")
			println(name.(string))
			foo := (input).([]interface{})
			for _, v := range foo {
				s.AssignTester(v, name.(string))
			}
		}
	case map[string]interface{}:
		{
			println("map[string]interface")
			foo := (input).(map[string]interface{})
			var field reflect.Value
			if name != nil {
				field = elem.FieldByName(name.(string))
			}
			if name == nil {
				for k, v := range foo {
					s.AssignTester(v, k)
				}
			} else if strings.Compare(name.(string), "") == 0 {
				s.AssignMap(field, foo)
			} else if strings.Compare(name.(string), "Request") == 0 {
				s.AssignMap(field, foo)
			} else if strings.Compare(name.(string), "Response") == 0 {
				s.AssignMap(field, foo)
			} else if strings.Compare(name.(string), "Receive") == 0 {
				s.AssignMap(field, foo)
			} else {

			}

		}
	default:
		{
			println("default")
			if strings.Compare(name.(string), "Request") == 0 {
				println("default Request")
			} else if strings.Compare(name.(string), "Response") == 0 {
				println("default Response")
			} else {

			}
			foo := (input).(map[string]interface{})
			for k, v := range foo {
				s.AssignTester(v, k)
			}

		}
	}
	return true
}

func (s *Jsoner) AssignMap(fieldmap reflect.Value, input interface{}) {
	Where()

	if fieldmap.CanSet() {
		for k, v := range input.(map[string]interface{}) {
			if strings.Compare("TEST", k) == 0 {
				println(v)
			} else {
				var valin string
				switch v.(type) {
				case float32:
					valin = strconv.FormatInt(int64(v.(float32)), 16)
				case float64:
					valin = strconv.FormatInt(int64(v.(float64)), 16)
				case string:
					valin = v.(string)
				default:

				}
				fieldmap.SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(valin))

			}

		}
	} else {
		println("map[string]interface CanSet Err")
	}
}

func (s *Jsoner) GetAbsolutePath() string {
	return s.abspath
}
